using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace UPA
{
    public class ProcessActionWindow: EditorWindow
    {
        private struct ActionGroupUnit
        {
            public ProcessActionGroup Group { get; }
            public string Guid { get; }
            
            public ActionGroupUnit(ProcessActionGroup group, string guid)
            {
                Group = group;
                Guid = guid;
            }
            
            // 过滤
            public bool Filter(string filter)
            {
                if (string.IsNullOrWhiteSpace(filter))
                {
                    return true;
                }
                return Group.name.Contains(filter,StringComparison.OrdinalIgnoreCase);
            }
        }
        [MenuItem("Window/流程自动化/管理窗口")]
        private static void Open()
        {
            GetWindow<ProcessActionWindow>().Show();  
        }

        private const string InspectorWidthKey = "ProcessActionWindow:InspectorWidth";
        private const string SelectGroupGuidKey = "ProcessActionWindow:SelectGroupGuid";
        
        private const float InspectorMinWidth = 350f;
        private const float LeftAreaMinWidth = 400;
        private const float WindowMinHeight = 300f;
        private const float ActionGroupBtnMinWidth = 45;
        private const float ActionGroupBtnHeight = 35;
        private const float SplitterWidth = 2; // 分割线的宽度
        
        private float _inspectorWidth;
        private readonly List<ActionGroupUnit> _actionGroupUnits = new();
        private ProcessActionGroupDrawer _groupDrawer;
        private string _selectGuid;
        private string _filter;
        private bool _inDrag;
        private GUIContent _tmpContent;

        private GUIStyle _textFieldStyle;
        private GUIStyle _btnStyle;

        private void Awake()
        {
            titleContent = new GUIContent( "流程自动化管理");
        }

        private void OnEnable()
        {
            _selectGuid = EditorPrefs.GetString(SelectGroupGuidKey);
            _inspectorWidth = Mathf.Max(EditorPrefs.GetFloat(InspectorWidthKey, InspectorMinWidth),InspectorMinWidth);
            minSize = new Vector2(InspectorMinWidth + LeftAreaMinWidth + SplitterWidth, WindowMinHeight);
            CacheActionGroup();
            RefreshInspector();
        }

        private void OnGUI()
        {
            if (_btnStyle == null)
            {
                _btnStyle = new (GUI.skin.button) { fontSize = 16 , stretchWidth = false};
                _textFieldStyle = new (GUI.skin.textField) { fontSize = 16};
                _tmpContent = new();
            }
            
            GUILayout.BeginVertical();

            var posRect = position;
            var leftRect = new Rect(0, 0, posRect.width - _inspectorWidth - SplitterWidth, posRect.height);
            var rightRect = new Rect(posRect.width - _inspectorWidth, 0, _inspectorWidth, posRect.height);
            var splitterRect = new Rect(posRect.width - _inspectorWidth - SplitterWidth, 0, SplitterWidth, posRect.height);
            
            DrawLeftArea(leftRect);
            
            EditorGUIUtility.AddCursorRect(splitterRect, MouseCursor.ResizeHorizontal);
            if (Event.current.type == EventType.MouseDown && splitterRect.Contains(Event.current.mousePosition))
            {
                _inDrag = true;
                GUI.FocusControl(null); // 取消其他控件的焦点
                Event.current.Use();
            }

            if (Event.current.type == EventType.MouseUp)
            {
                _inDrag = false;
            }
            if (Event.current.type == EventType.MouseDrag && _inDrag)
            {
                var oldWidth = _inspectorWidth;
                var inspectorMaxWidth = posRect.width - SplitterWidth - LeftAreaMinWidth;
                _inspectorWidth = Mathf.Clamp(_inspectorWidth - Event.current.delta.x,InspectorMinWidth,inspectorMaxWidth);
                if (!Mathf.Approximately(oldWidth, inspectorMaxWidth))
                {
                    EditorPrefs.SetFloat(InspectorWidthKey,_inspectorWidth);
                }
               
                Event.current.Use();
            }
            var originColor = GUI.color;
            GUI.color = Color.black;
            GUI.Box(splitterRect,GUIContent.none);
            GUI.color = originColor;
            
            DrawRightArea(rightRect);

            GUILayout.EndVertical();
        }

        private void DrawLeftArea(Rect rect)
        {
            GUILayout.BeginArea(rect);
            // menu
            GUILayout.BeginHorizontal();
            _filter = GUILayout.TextField(_filter,_textFieldStyle);
            if (GUILayout.Button("刷新",_btnStyle))
            {
                CacheActionGroup();
            }
            GUILayout.EndHorizontal();
            
            float remainWidth = rect.width;
            GUILayout.BeginHorizontal();
            foreach (var unit in _actionGroupUnits)
            {
                if (!unit.Filter(_filter))
                {
                    continue;
                }

                _tmpContent.text = unit.Group.name;
                var width = Mathf.Max(ActionGroupBtnMinWidth,_btnStyle.CalcSize(_tmpContent).x);
                if (remainWidth < width)
                {
                    GUILayout.EndHorizontal();
                    GUILayout.BeginHorizontal();
                    remainWidth = rect.width;
                }

                remainWidth -= width;
                if (unit.Guid == _selectGuid)
                {
                    var originColor = GUI.color;
                    GUI.color = Color.gray;
                    GUILayout.Label(unit.Group.name,_btnStyle,GUILayout.Width(width),GUILayout.Height(ActionGroupBtnHeight));
                    GUI.color = originColor;
                }
                else
                {
                    if(GUILayout.Button(unit.Group.name,_btnStyle,GUILayout.Width(width),GUILayout.Height(ActionGroupBtnHeight)))
                    {
                        _selectGuid = unit.Guid;
                        EditorPrefs.SetString(SelectGroupGuidKey,_selectGuid);
                        RefreshInspector();
                    }
                }
            }
            GUILayout.EndHorizontal();
            
            GUILayout.EndArea();
        }

        private void DrawRightArea(Rect rect)
        {
            GUILayout.BeginArea(rect);
            if (_groupDrawer)
            {
                _groupDrawer.OnInspectorGUI();
            }
            GUILayout.EndArea();
        }

        private void CacheActionGroup()
        {
            var guids = AssetDatabase.FindAssets($"t:{nameof(ProcessActionGroup)}");
            foreach (var guid in guids)
            {
                var path = AssetDatabase.GUIDToAssetPath(guid);
                var asset = AssetDatabase.LoadAssetAtPath<ProcessActionGroup>(path);
                if (asset)
                {
                    _actionGroupUnits.Add(new (asset,guid));
                }
            }
        }

        private void RefreshInspector()
        {
            foreach (var unit in _actionGroupUnits)
            {
                if (unit.Guid == _selectGuid)
                {
                    _groupDrawer = Editor.CreateEditor(unit.Group) as ProcessActionGroupDrawer;
                    return;
                }
            }
        }
    }
}